package com.qfedu.edu.config;

import com.qfedu.edu.constance.RabbitMQConstance;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.retry.MessageRecoverer;
import org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;

import java.util.HashMap;
import java.util.Map;

/**
 * @author xiaobobo
 * @title: RabbitMQConfig
 * @projectName cd-fy-2401-third-project-parent
 * @description: 这个是咋们的RabbitMQ的配置文件
 * @date 2024/10/9  16:41
 */
@SpringBootConfiguration
@ConditionalOnProperty(name = "framework.config.mq", havingValue = "true")
public class RabbitMQConfig {

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate();
        rabbitTemplate.setConnectionFactory(connectionFactory);
        //设置rabbitTemplate支持事务
        rabbitTemplate.setChannelTransacted(true);
        return rabbitTemplate;
    }

    /**
     * 防止少卖的这个队列
     * @return
     */
    @Bean
    public Queue orderExpireQueue(){
        //申明一个map
        Map<String,Object> maps=new HashMap<>();
        //向map中添加参数(3分钟时间过期)
        maps.put("x-message-ttl",3*60*1000);
        maps.put("x-dead-letter-exchange","deadExchange");
        return new Queue(
                RabbitMQConstance.getOrderExpireName(),
                true,
                false,
                false,maps);
    }

    @Bean
    public FanoutExchange deadExchange(){
        return new FanoutExchange("deadExchange",true,false);
    }

    @Bean
    public Queue orderTTLQueue(){
        return new Queue(
                RabbitMQConstance.getOrderTtlName(),
                true,
                false,
                false);
    }

    // 将队列绑定到交换机
    @Bean
    public Binding binding77(Queue orderTTLQueue,FanoutExchange deadExchange){
       return BindingBuilder.bind(orderTTLQueue).to(deadExchange);
    }

    /**
     * 减库存的队列的申明
     * @return
     */
    @Bean
    public Queue stockQueue(){
        return new Queue(
                RabbitMQConstance.getStockReduceName(),
                true,
                false,
                false);
    }
    @Bean
    public Queue orderQueue(){
        return new Queue(
                RabbitMQConstance.getOrderName(),
                true,
                false,
                false);
    }


    /**
     * 这里首先申明一个队列
     * 这个队列的主要功能是同步MySQL中的数据到 ES中的这个数据同步队列
     * @return
     */
    @Bean
    public Queue mysqlToMqQueue(){
        return new Queue(
                RabbitMQConstance.getMysqlMqName(),
                true,
                false,
                false);
    }

    //定义一个发布订阅模型的交换机

    @Bean
    public FanoutExchange fanoutExchangeMySQLToMqQueue(){
        return new FanoutExchange("fanoutExchangeMySQLToMqQueue");
    }

    //将队列绑定到交换机上

    @Bean
    public Binding binding9(Queue mysqlToMqQueue,FanoutExchange fanoutExchangeMySQLToMqQueue){
        return BindingBuilder.bind(mysqlToMqQueue).to(fanoutExchangeMySQLToMqQueue);
    }



    //所以要解决 消费成功业务执行失败的问题
    /**
     * 这个是咋们的异常交换机
     * @return
     */
    @Bean
    public FanoutExchange fanoutExceptionExchange(){
        return new FanoutExchange("fanoutExceptionExchange");
    }

    @Bean
    public Queue exceptionQueue(){
       return new Queue("exceptionQueue",true,false,false);
    }

    //将异常队列 绑定到 异常交换机
    @Bean
    public Binding binding1(Queue exceptionQueue,FanoutExchange fanoutExceptionExchange){
        return BindingBuilder.bind(exceptionQueue).to(fanoutExceptionExchange);
    }

    //接下来就是重试策略
    //接下来就是重试多次之后依然失败的处理方式(第一种处理方式)
    @Bean
    public MessageRecoverer messageRecoverer(RabbitTemplate rabbitTemplate){
        return new RepublishMessageRecoverer(rabbitTemplate,"fanoutExceptionExchange","");
    }

    //申明一个通道
    /**
     * 申明这个通道的目的是为了找到队列中的消费者的个数 以及消息的个数
     * @param connectionFactory
     * @return
     */
    @Bean
    public Channel channel(ConnectionFactory connectionFactory){
        return connectionFactory.createConnection().createChannel(true);
    }


}
